package com.techshinogongjian.fp.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;

import com.fingerUsb.OnConnectListener;
import com.techshinogongjian.fp.client.TcFingerClient;
import com.techshinogongjian.fp.comm.LaserXComm;
import com.techshinogongjian.fp.comm.TwoSerialComm;
import com.techshinogongjian.fp.func.IFingerprintFunc;
import com.techshinogongjian.fp.func.LaserXFuncImpl;
import com.techshinogongjian.fp.func.TwoSerialFuncImpl;

/**
 * 蓝牙工具类
 * 
 * @author wangzhi
 */
public class BluetoothUtil {

	private static final String TAG = BluetoothUtil.class.getSimpleName();

	private static BluetoothUtil mInstance;
	private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter
			.getDefaultAdapter();

	public enum Protocol {
		LASERX, TWO
	}

	private Protocol mProtocol = Protocol.LASERX;

	private Context mContext;

	private BluetoothDevice mDevice;
	private BluetoothSocket mSocket;

	private IFingerprintFunc mFingerprintFunc;
	private OutputStream mOutputStream;
	private InputStream mInputStream;

	private OnConnectListener mOnConnectListener;
	private Handler mHandler = new Handler();

	// 蓝牙通信已连接
	private boolean bCommConnected = false;

	private BluetoothUtil(Context context) {
		mContext = context;
	}

	public static BluetoothUtil getInstance( Context context) {
		if (mInstance == null) {
			mInstance = new BluetoothUtil(context);
		}
		return mInstance;
	}

	public void setProtocol(Protocol protocol) {
		mProtocol = protocol;
	}

	public IFingerprintFunc getFingerprintFunc() {
		return mFingerprintFunc;
	}

	/**
	 * 连接设备
	 */
	public void connectDevice() {
		Logs.i(TAG, "device state:" + mDevice.getBondState());

		ExecutorUtil.execSingle(new Runnable() {

			@Override
			public void run() {
				if (isConnected()) {
					mHandler.post(new Runnable() {

						@Override
						public void run() {
							connectFailed(FpConst.TCY_FAIL, "已连接");
						}
					});
				} else {
					asynConnect();
				}
			}
		});
	}

	/**
	 * 断开设备
	 */
	public void disconnectDevice() {

		ExecutorUtil.execSingle(new Runnable() {
			@Override
			public void run() {
				asynDisConnect();
			}
		});
	}

	private void asynConnect() {
		Logs.i(TAG, "asynConnect...");

		try {
			if (bCommConnected) {
				asynDisConnect();
				Thread.sleep(50);
			}

			Method method = mDevice.getClass().getMethod("createRfcommSocket",
					new Class[] { int.class });

			mSocket = (BluetoothSocket) method.invoke(mDevice,
					Integer.valueOf(1));

			mBluetoothAdapter.cancelDiscovery();
			mSocket.connect();

			mInputStream = mSocket.getInputStream();
			mOutputStream = mSocket.getOutputStream();

			if (mProtocol == Protocol.LASERX) {
				mFingerprintFunc = new LaserXFuncImpl(new LaserXComm(
						mInputStream, mOutputStream));
			} else {
				mFingerprintFunc = new TwoSerialFuncImpl(new TwoSerialComm(
						mInputStream, mOutputStream));
			}
			connected();
		} catch (Exception e) {
			connectFailed(-1, e.getMessage());
			e.printStackTrace();
		}
	}

	private void asynDisConnect() {
		bCommConnected = false;
		mFingerprintFunc = null;
		Logs.i(TAG, "asynDisConnect...");
		try {
			mBluetoothAdapter.cancelDiscovery();
			Logs.i(TAG, "关闭mOutputStream");
			if (mOutputStream != null)
				mOutputStream.close();
			Logs.i(TAG, "关闭mInputStream");
			if (mInputStream != null)
				mInputStream.close();
			Logs.i(TAG, "关闭mSocket");
			if (mSocket != null)
				mSocket.close();
			Logs.i(TAG, "关闭成功...");
		} catch (IOException e) {
			Logs.i(TAG, "关闭失败..." + e.getMessage());
			connectFailed(-1, e.getMessage());
			e.printStackTrace();
		}
	}

	private void connected() {
		bCommConnected = true;
		if (mOnConnectListener != null) {
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					mOnConnectListener.onConnected(1,new TcFingerClient(
							mFingerprintFunc, mContext),null);
				}
			});
		}
	}

	private void connectFailed(final int code, final String msg) {
		if (mOnConnectListener != null) {
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					mOnConnectListener.onConnectFailed(code, msg);
					;
				}
			});
		}
	}

	public boolean isConnected() {
		if (mFingerprintFunc == null) {
			return false;
		}
		return mFingerprintFunc.isConnected();
	}

	public void setDevice(BluetoothDevice device) {
		mDevice = device;
	}

	public void setOnConnectListener(OnConnectListener connectListener) {
		mOnConnectListener = connectListener;
	}

}
